using System;
using System.Collections.Generic;
using System.Diagnostics;

namespace Mbs.Elements
{
    [DebuggerDisplay("Id={Id},Text={Text},Enabled={Enabled},Visible={Visible}")]
	public abstract class Element<TUIElement> : MarshalAndDisposableObject, IElement,ICommandRepository
	{
        protected Element()
        {
            commands = new List<string>();
        }

        private List<string> commands;

        protected abstract TUIElement DoAdd(TUIElement uiElement);

        protected abstract void DoRemove(TUIElement uiElement);

        public object Target { get; protected set; }

		public void Add(object uiElement)
		{
            if (uiElement == null)
                throw new ArgumentNullException("uiElement");

            TUIElement element = GetTypedElement(uiElement);
          
			Target = DoAdd(element);
		}

		public void Remove(object uiElement)
		{
            if (uiElement == null)
                return;

            TUIElement element = GetTypedElement(uiElement);
            
			DoRemove(element);
		}

        private TUIElement GetTypedElement(object uiElement)
		{
            if (!(uiElement is TUIElement))
			{
				throw new ArgumentException(uiElement.ToString());
			}

            return (TUIElement)uiElement;
		}

        public abstract string Name { get; set; }
        public abstract string Text { get; set; }

        public abstract bool? Enabled { get; set; }
        public abstract bool? Visible { get; set; }

        public virtual object Tag { get; set; }

        public ICommandRepository Commands
        {
            get { return this; }
        }

       
        #region ICommandRepository Members

        void ICommandRepository.Add(string command)
        {
            if (string.IsNullOrEmpty(command))
                return;
            if (commands.Contains(command))
                return;
            commands.Add(command);
        }

        void ICommandRepository.Remove(string command)
        {
            if (string.IsNullOrEmpty(command))
                return;
            if (!commands.Contains(command))
                return;
            commands.Remove(command);
        }

        IDisposable ICommandRepository.UpdateCommand(string oldCommand, string newCommand)
        {
            if (!commands.Contains(oldCommand))
                return DisposeAction.Empty;

            commands.Remove(oldCommand);
            commands.Add(newCommand);

            var cmd = oldCommand.Command();
            var @event = cmd.RemoveElement(this);
            if (!string.IsNullOrEmpty(@event))
                return newCommand.Command().Attach(Target, @event);

            return DisposeAction.Empty;
        }

        int ICommandRepository.Count
        {
            get { return commands.Count; }
        }

        string[] ICommandRepository.GetCommands()
        {
            return commands.ToArray();
        }

        #endregion
    }
}
